package com.idgenerate.demo.service.redis.impl;

import com.idgenerate.demo.service.redis.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Created by 蒋时华 on 2017/9/21.
 */
@Service
public class RedisServiceImpl implements RedisService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean set(final String key, Object value) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean setStr(final String key, String value) {
        boolean result = false;
        try {
            ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
            stringStringValueOperations.set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean set(final String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public void remove(final String... keys) {
        for (String key : keys) {
            remove(key);
        }
    }

    @Override
    public void removePattern(final String pattern) {
        try{
            Set<Serializable> keys = redisTemplate.keys(pattern);
            if (keys.size() > 0)
                redisTemplate.delete(keys);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void remove(final String key) {
        try{
            if (exists(key)) {
                redisTemplate.delete(key);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public boolean exists(final String key) {
        try{
            return redisTemplate.hasKey(key);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public Object get(final String key) {
        try{
            Object result = null;
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            result = operations.get(key);
            return result;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void hmSet(String key, Object hashKey, Object value){
        try{
            HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
            hash.put(key,hashKey,value);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public Object hmGet(String key, Object hashKey){
        try{
            HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
            return hash.get(key,hashKey);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void lPush(String k,Object v){
        try{
            ListOperations<String, Object> list = redisTemplate.opsForList();
            list.rightPush(k,v);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public List<Object> lRange(String k, long l, long l1){
        try{
            ListOperations<String, Object> list = redisTemplate.opsForList();
            return list.range(k,l,l1);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void add(String key,Object value){
        try{
            SetOperations<String, Object> set = redisTemplate.opsForSet();
            set.add(key,value);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public Set<Object> setMembers(String key){
        try{
            SetOperations<String, Object> set = redisTemplate.opsForSet();
            return set.members(key);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void zAdd(String key,Object value,double scoure){
        try{
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            zset.add(key,value,scoure);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public Set<Object> rangeByScore(String key,double scoure,double scoure1){
        try{
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            return zset.rangeByScore(key, scoure, scoure1);
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void setDB(Integer index){
        try{
            JedisConnectionFactory connectionFactory = (JedisConnectionFactory) redisTemplate.getConnectionFactory();
            connectionFactory.setDatabase(index);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 设置一个自增的数据
     * @param key
     * @param growthLength
     */
    @Override
    public Long incr(String key,Long growthLength){
        return redisTemplate.opsForValue().increment(key, growthLength);
    }

    private String getOrderIdPrefix(){
        LocalDateTime localDateTime = LocalDateTime.now();
        // 年+一年中的多少天+一天中的小时+redis自增
        int year = localDateTime.getYear()- 2000;
        int day = localDateTime.getDayOfYear();
        int hour = localDateTime.getHour();
        String dayFormat = String.format("%1$03d",day);
        String hourFormat = String.format("%1$02d",hour);
        return new StringBuffer().append(year).append(dayFormat).append(hourFormat).toString();
    }

    @Override
    public Long getId(){
        String IdPrefix = this.getOrderIdPrefix();
        String key = "id_"+IdPrefix;
        String ordreId = null;
        try{
            Long index = this.incr(key, 1L);
            // 开关 1分钟 数据加密 归零
            // 很好的扩容
            redisTemplate.expire(key, 1, TimeUnit.MINUTES);
            ordreId = IdPrefix + String.format("%1$05d", index);
            return Long.valueOf(ordreId);
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("从redis中获取id失败");
        }
        return null;
    }

}
